<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简单编辑器</title>
    <script type="text/javascript">
    window.$ = jQuery = require('./jquery-3.5.1.min.js');
    </script>
    <style type="text/css">
    #autocomplete {
        width: 150px;
        max-height: 200px;
        overflow: auto;
        position: absolute;
        background-color: rgb(255, 255, 255);
        border: 1px black solid;
        display: none;
    }
    #autocomplete ul {
        padding: 0;
        margin: 0;
    }
    #autocomplete li {
        list-style: none;
        border-top: 1px black solid;
        border-bottom: 1px black solid;
    }
    #autocomplete .active {
        background-color: rgb(0, 159, 255);
        color: white;
    }
    .line {
        min-height: 25px;
        line-height: 25px;
        color: white;
        font-size: 20px;
        background-color: rgb(0, 159, 255);
        padding: 0 10px;
        margin: 10px 0;
    }
    </style>
</head>
<body>
    <div id="autocomplete">
        <ul>
        </ul>
    </div>

    <div style="margin-bottom: 15px;">
        <label>文件路径</label>
        <input type="text" id="file_path_input">
        <button type="button" onclick="open_file();">打开文件</button>
        <button type="button" onclick="save_file();">保存文件</button>
    </div>
    <div id="content"></div>

    <script type="text/javascript">
        var fs = require('fs');

        var has_shift = false;
        var center_code = '';

        var has_ctrl = false;

        var list = ['abstract', 'and', 'array', 'as', 
                    'break', 'case', 'catch','class',
                    'clone', 'const', 'continue','declare', 'default',
                    'die', 'do', 'echo','else', 'elseif',
                    'empty', 'enddeclare', 'endfor','endforeach', 'endif',
                    'endswitch', 'endwhile', 'eval','exit', 'extends',
                    'final', 'finally', 'for','foreach', 'function',
                    'global', 'goto', 'if','implements', 'include',
                    'include_once', 'instanceof', 'insteadof','	interface', 'isset',
                    'list', 'namespace', 'new','or', 'print',
                    'private', 'protected', 'public','require', 'require_once',
                    'return', 'static', 'switch','throw', 'trait',
                    'try', 'unset', 'use','var', 'while',
                    'xor'];

        $(function () {
            execute_script('head.simple');
            var div = add_div();
            $('#content').append(div);
            $('html').on('keydown', function (event) {
                if (event.key === 'Control') {
                    has_ctrl = true;
                }
            });
            $('html').on('keyup', function (event) {
                if (event.key === 'Control') {
                    has_ctrl = false;
                } else if (has_ctrl === true && 
                        (event.key === 's' || event.key === 'S')) {
                    save_file();
                } else if (event.key === 'Control') {
                    has_ctrl = false;
                }
            });
        });

        function open_file() {
            var file_path_input = document.getElementById('file_path_input');
            var file_path = file_path_input.value;
            if (fs.existsSync(file_path)) {
                var file_content = fs.readFileSync(file_path);
                file_content = file_content.toString();
                var code_lines = file_content.split('\n');
                $('#content').empty();
                for (index in code_lines) {
                    var line = code_lines[index];
                    line = line.replace('<', '&lt;');
                    line = line.replace('>', '&gt;');
                    var div = add_div(line);
                    $('#content').append(div);
                }
                $('#content div').last().focus();
            } else {
                alert('文件不存在');
            }
        }

        function save_file() {
            var file_path_input = document.getElementById('file_path_input');
            var file_path = file_path_input.value;
            var file_content = '';
            $('#content div').each(function () {
                file_content += $(this).text();
            });
            fs.writeFileSync(file_path, file_content);
            alert('文件保存成功');
        }

        function add_new_content_div(current_div) {
            var div = add_div();
            current_div.after(div);
            div.focus();
        }

        function get_autocomplete_list(baseOffset, div) {
            $('#autocomplete ul').empty();
            for (index in list) {
                var v = list[index];
                if (v.substr(0, center_code.length) === center_code) {
                    var li = $('<li></li>');
                    li.html(v);
                    $('#autocomplete ul').append(li);
                }
            }
            $('#autocomplete ul li').first().addClass('active');
            if ($('#autocomplete ul li').length === 0) {
                $('#autocomplete').css('display', 'none');
            } else {
                $('#autocomplete').css('display', 'block');
            }
        }

        function add_div(content) {
            var div = $('<div></div>');
            div.addClass('line');
            div.attr('contenteditable', true);
            if (content !== null && content !== undefined) {
                div.html(content);
            }
            div.on('keydown', function (event) {
                if (event.code === 'Enter') {
                    event.preventDefault();
                } else if (event.key === 'Shift') {
                    has_shift = true;
                }
            });
            div.on('keyup', function (event) {
                if (event.key === 'Shift') {
                    has_shift = false;
                } else if (event.code === 'Enter') {
                    event.preventDefault();
                    if ($('#autocomplete').css('display') !== 'none') {
                        var selection = document.getSelection();
                        var before_text = $('.focus-line').html().substr(0, selection.baseOffset).replace('&nbsp;', ' ');
                        var center_text = $('#autocomplete .active').html().substr(center_code.length);
                        var after_text = $('.focus-line').html().substr(before_text.length);
                        $('.focus-line').html(before_text + center_text + after_text);
                        $('#autocomplete ul').empty();
                        $('#autocomplete').css('display', 'none');
                    } else {
                        add_new_content_div($(this));
                    }
                } else if ((event.keyCode >= 65 && event.keyCode <= 90) ||
                            (event.keyCode >= 97 && event.keyCode <= 122)) {
                    var selection = document.getSelection();
                    if (has_shift === true) {
                        center_code += String.fromCharCode(event.keyCode);
                    } else {
                        center_code += String.fromCharCode(event.keyCode + 32);
                    }
                    get_autocomplete_list(selection.baseOffset, $(this));
                    $('#autocomplete').css({
                        'left': (selection.baseOffset) * 20 + 10,
                        'top': $('.focus-line').prevAll().length * 55 + 50
                    });
                } else if (event.key === 'ArrowDown') {
                    var active_node = $('#autocomplete .active');
                    var next_node = active_node.next();
                    if (next_node.length > 0) {
                        next_node.addClass('active');
                        active_node.removeClass('active');
                    }
                } else if (event.key === 'ArrowUp') {
                    var active_node = $('#autocomplete .active');
                    var prev_node = active_node.prev();
                    if (prev_node.length > 0) {
                        prev_node.addClass('active');
                        active_node.removeClass('active');
                    }
                } else if (event.key === 'Backspace') {
                    $('#autocomplete').css('display', 'none');
                    if ($(this).text() === '' && $('#content div').length > 1) {
                        $(this).prev().focus();
                        $(this).remove();
                    }
                } else if (event.key === ' ') {
                    center_code = '';
                } else if (event.key === 'Delete') {
                    $('#autocomplete').css('display', 'none');
                    if ($(this).text() === '' && $('#content div').length > 1) {
                        $(this).next().focus();
                        $(this).remove();
                    }
                }
            });
            div.on('focus', function () {
                $('#content .line').removeClass('focus-line');
                $(this).addClass('focus-line');
            });
            div.on('blur', function () {
                var code_text = $(this).text();
                var code_word = '';
                var code_index = 0;
                var code_line = '';
                for (index in code_text) {
                    var c = code_text[index];
                    if (c === ' ') {
                        code_index += code_word.length + 1;
                        code_line += code_word + ' ';
                        code_word = '';
                    } else {
                        code_word += c;
                    }
                    if (list.indexOf(code_word) > -1) {
                        var before = code_line.substr(0, code_index);
                        var after = code_line.substr(code_index);
                        code_word = '<span style="color: black;">' + code_word + '</span>';
                        code_line = before + code_word + after;
                        code_index += code_word.length;
                        code_word = '';
                    }
                }
                code_line += code_word;
                $('.focus-line').html(code_line);
            });
            div.on('click', function () {
                execute_script('code_line_clicked.simple', $(this));
            });
            return div;
        }

        function execute_script(script_name, extern_param) {
            var content = fs.readFileSync(script_name).toString();
            var lines = content.split('\n');
            for (i in lines) {
                var line = lines[i];
                var code_line = line.split(' ');
                var cmd = code_line[0];
                var param = code_line[1];
                if (cmd === 'alert') {
                    if (param.indexOf('{') > -1) {
                        param = param.replace('{code_line_index}', extern_param.prevAll().length + 1);
                        alert(param);
                    } else {
                        alert(param);
                    }
                }
            }
        }
    </script>
</body>
</html>
